<!--
 * @Description:
 * @Author bianpengfei
 * @create 2021/5/17 15:25
 -->
<template>
  <div class="page">
    <div class="page__body">
      <span class="container__top-tag">湖</span>
      <span class="container__top-tag">源</span>
      <span class="container__top-tag">仓</span>

      <!--中间内容-->
      <div ref="efContainer" class="page__body-container" tabindex="10">
        <div ref="containerLeft" class="container-left"></div>
        <div ref="containerCenter" class="container-center"></div>
        <div ref="containerRight" class="container-right">
          <div ref="rightScroll" class="container-right__inner">
            <div class="right__inner"></div>
            <slot name="right" v-bind="{ nodeList: _rightNodeList }"></slot>
          </div>
        </div>
        <slot v-bind="{ nodeList: _mainNodeList }"></slot>
      </div>
    </div>
  </div>
</template>

<script>
import BUtils from '@bianpengfei/utils'

export default {
  components: {},

  directives: {},
  mixins: [jsplumbMixins],

  props: {
    // 节点位置信息
    nodeList: {
      type: Array,
      default: () => []
    },

    // 连线关系信息
    lineList: {
      type: Array,
      default: () => []
    }
  },

  data () {
    return {
      loadEasyFlowFinish: false // 是否加载完毕标志位
    }
  },

  computed: {
    _nodeList: {
      get() {
        return this.nodeList.map((v) => {
          v._x = v.x
          v._y = v.y
          if (v.area) {
            switch (String(v.area).toUpperCase()) {
              case 'A': {
                v.x = v.x + this._containerRange.A.minX
                break
              }
              case 'B': {
                v.x = v.x + this._containerRange.B.minX
                break
              }
              case 'C': {
                v.y = v._y + this.$refs?.rightScroll?.scrollTop || 0
                break
              }
              default: {
                break
              }
            }
          }
          return v
        })
      },
      set(val = []) {
        let nodeList = val.map((v) => {
          v._x = v.x
          v._y = v.y
          if (v.area) {
            switch (String(v.area).toUpperCase()) {
              case 'A': {
                v.x = v.x + this._containerRange.A.minX
                break
              }
              case 'B': {
                v.x = v.x + this._containerRange.B.minX
                break
              }
              case 'C': {
                v.y = v._y + this.$refs.rightScroll.scrollTop
                break
              }
              default: {
                break
              }
            }
          }
          return v
        })
        this.$emit('update:nodeList', nodeList)
      }
    },

    _lineList: {
      get() {
        return this.lineList
      },
      set(val) {
        this.$emit('update:lineList', val)
      }
    },

    // 右侧节点数据
    _rightNodeList() {
      return Array.isArray(this._nodeList)
        ? this._nodeList.filter((v) => ['C'].includes(v.area && v.area.toString().toUpperCase()))
        : []
    },

    _mainNodeList() {
      return Array.isArray(this._nodeList)
        ? this._nodeList.filter((v) => ['A', 'B'].includes(v.area && v.area.toString().toUpperCase()))
        : []
    }
  },

  watch: {
    _nodeList: {
      handler() {
        this.reloadData()
      }
    },

    _lineList: {
      handler() {
        this.reloadData()
      }
    }
  },

  async mounted() {
    // eslint-disable-next-line no-undef
    if (!window.jsPlumb) {
      this.$message.error('资源请求失败')
      return
    }
    this.addEventListener()
    this.reloadData()
  },

  activated() {
    this.addEventListener()
  },

  deactivated() {
    this.removeEventListener()
  },

  beforeDestroy () {
    this.removeEventListener()
  },

  methods: {
    /**
     * 加载流程图
     */
    reloadData () {
      this._jsPlumb = window.jsPlumb.getInstance()
      this.$nextTick(() => {
        this.jsPlumbInit()
        this.$nextTick(() => {
          let childs = Array.from(this.$refs.rightScroll.children)
          let lastChild = childs.at(-1)
          let top = getComputedStyle(lastChild).top
          this.$refs.rightScroll.querySelector('.right__inner').style.height = `${
            parseInt(top) + parseInt(lastChild.offsetHeight)
          }px`
        })
      })
    },

    /* 添加事件监听*/
    addEventListener () {
      this._resizeObserve = (event) => {
        const { containerLeft, containerCenter, containerRight } = this.$refs
        let left = { minX: 0, maxX: containerLeft.offsetWidth }
        let center = { minX: left.maxX, maxX: left.maxX + containerCenter.offsetWidth }
        let right = { minX: center.maxX, maxX: center.maxX + containerRight.offsetWidth }
        this._containerRange = {
          A: left,
          B: center,
          C: right
        }
        console.log('_containerRange', this._containerRange)
        this.$nextTick(() => {
          this._jsPlumb && this._jsPlumb.setSuspendDrawing(false, true)
        })
      }
      this._resizeObserveDebounce = BUtils.debounce(this._resizeObserve, 500)
      window.addEventListener('resize', this._resizeObserveDebounce, false)

      this._rightContainerScroll = (event) => {
        console.log(event.target)
        // let target = event.target
        //
        // let nodeListObj = this.data.nodeList.reduce((pre, cur) => {
        //   pre[cur.id] = cur
        //   return pre
        // }, {})

        setTimeout(() => {
          this._jsPlumb && this._jsPlumb.setSuspendDrawing(false, true)
        })

        // this.data.lineList
        //   .filter(v => ['C'].includes(nodeListObj[v.from].area) || ['C'].includes(nodeListObj[v.to].area))
        //   .map(v => {
        //     return {
        //       ...v,
        //       _conn: this._jsPlumb.getConnections({
        //         source: v.from,
        //         target: v.to
        //       })?.[0]
        //     }
        //   })
        //   .filter(Boolean)
        //   .map(v => {
        //     console.log('删除')
        //     v._conn && this._jsPlumb.deleteConnection(v._conn)
        //     return v
        //   })
        //   .forEach(v => {
        //     console.log('存在', v)
        //     const connParam = {
        //       source: v.from,
        //       target: v.to,
        //       label: v.label || '',
        //       connector: v.connector || '',
        //       anchors: v.anchors,
        //       paintStyle: v.paintStyle,
        //       overlays: [
        //         v.arrow !== false && [
        //           'Arrow',
        //           {
        //             width: 10, // 箭头尾部的宽度
        //             length: 8, // 从箭头的尾部到头部的距离
        //             location: 1, // 位置，建议使用0～1之间
        //             direction: 1, // 方向，默认值为1（表示向前），可选-1（表示向后）
        //             foldback: 0.623 // 折回，也就是尾翼的角度，默认0.623，当为1时，为正三角
        //           }
        //         ]
        //       ].filter(Boolean)
        //     }
        //     this._jsPlumb.connect(connParam, this.jsplumbConnectOptions)
        //   })
      }
      this._rightContainerScrollThrottle = BUtils.throttle(this._rightContainerScroll, 10)
      this.$refs.rightScroll.addEventListener('scroll', this._rightContainerScrollThrottle, false)
      this._resizeObserve()
      this._rightContainerScroll()
    },

    /* 移除事件监听*/
    removeEventListener () {
      window.removeEventListener('resize', this._resizeObserveDebounce)
      this.$refs.containerRight.addEventListener('scroll', this._rightContainerScrollThrottle)
    },

    jsPlumbInit () {
      this._jsPlumb.ready(async () => {
        // 导入默认配置
        this._jsPlumb.importDefaults(this.jsplumbSetting)
        // 会使整个jsPlumb立即重绘。
        this._jsPlumb.setSuspendDrawing(false, true)
        // 初始化节点
        this.loadEasyFlow()

        // 单点击了连接线, https://www.cnblogs.com/ysx215/p/7615677.html
        this._jsPlumb.bind('dblclick', (conn, originalEvent) => {
          console.log('点击连线', conn, conn.getLabel())
          this.activeElement.type = 'line'
          this.activeElement.sourceId = conn.sourceId
          this.activeElement.targetId = conn.targetId
        })

        this._jsPlumb.setContainer(this.$refs.efContainer)
      })
    },

    /**
     * 加载流程
     */
    loadEasyFlow () {
      // if (this._jsPlumb) this._jsPlumb.reset()

      // 初始化节点
      this._nodeList.forEach((node) => {
        this._jsPlumb.unmakeSource(node.id)
        this._jsPlumb.unmakeTarget(node.id)
        this._jsPlumb.makeSource(node.id, this.jsplumbSourceOptions) // 设置源点，可以拖出线连接其他节点
        this._jsPlumb.makeTarget(node.id, this.jsplumbTargetOptions) // 设置目标点，其他源点拖出的线可以连接该节点
        //   this._jsPlumb.draggable(node.id, {  // 设置拖拽
        //     // containment: 'parent',
        //     stop: el => {
        //       // 拖拽节点结束后的对调
        //       console.log('拖拽结束: ', el)
        //     }
        //   })
      })

      // 初始化连线
      this._lineList.forEach((v) => {
        const connParam = {
          source: v.from,
          target: v.to,
          label: v.label || '',
          connector: v.connector || '',
          anchors: v.anchors,
          paintStyle: v.paintStyle,
          overlays: [
            v.arrow !== false && [
              'Arrow',
              {
                width: 10, // 箭头尾部的宽度
                length: 8, // 从箭头的尾部到头部的距离
                location: 1, // 位置，建议使用0～1之间
                direction: 1, // 方向，默认值为1（表示向前），可选-1（表示向后）
                foldback: 0.623 // 折回，也就是尾翼的角度，默认0.623，当为1时，为正三角
              }
            ]
          ].filter(Boolean)
        }
        this._jsPlumb.connect(connParam, this.jsplumbConnectOptions)
      })
      this.loadEasyFlowFinish = true
    }
  }
}
</script>

<style lang="scss" scoped>
.page {
  .page__body {
    //height: inherit;
    padding: 12px 0;
    height: 500px;
    position: relative;
    & > .container__top-tag {
      padding: 2px 12px;
      font-size: 12px;
      border-radius: 2px;
      background: #8c8c8c;
      color: #fff;
      position: absolute;
      z-index: 100;
      &:nth-of-type(1) {
        left: calc(15.5% / 2);
        transform: translate(-50%, -50%);
      }
      &:nth-of-type(2) {
        left: calc(15.5% + 54% / 2);
        transform: translate(-50%, -50%);
      }
      &:nth-of-type(3) {
        left: calc(15.5% + 54% + 30.5% / 2);
        transform: translate(-50%, -50%);
      }
    }
    & > .page__body-container {
      height: inherit;
      position: relative;
      border: 1px dashed #8c8c8c;
      display: flex;
      overflow-y: hidden;
      .container-left {
        width: 15.5%;
        //background: lightgreen;
        height: 100%;
        position: relative;
      }

      .container-center {
        width: 54%;
        //background: lightcoral;
        height: 100%;
        position: relative;
        border-left: 1px solid #d9d3d3;
        border-right: 1px solid #d9d3d3;
      }

      .container-right {
        width: 30.5%;
        //background: palegoldenrod;
        height: 100%;
        position: relative;
        padding: 0;
        .container-right__inner {
          position: relative;
          height: inherit;
          overflow-y: auto;
        }
        .container__top-tag {
          z-index: 10;
        }
      }

      .figure-circle-item {
        width: fit-content;
        height: fit-content;
        position: absolute;
        z-index: 10;
        font-size: 0;
        text-align: center;
        $circle-width: 40px;
        $gutter-width: 2px;
        .figure-circle {
          display: inline-block;
          width: $circle-width;
          height: $circle-width;
          border-radius: 50%;
          border: 1px solid #8c8c8c;
        }
        .figure-circle-label {
          font-size: 12px;
          width: $circle-width;
          display: inline-block;
          &.figure-circle-label--top {
            position: absolute;
            bottom: calc(#{$circle-width} + #{$gutter-width});
            left: 0;
            text-align: center;
          }
          &.figure-circle-label--right {
            position: absolute;
            left: calc(#{$circle-width} + #{$gutter-width});
            display: flex;
            align-items: center;
            min-height: $circle-width;
            text-align: left;
          }
          &.figure-circle-label--bottom {
            position: absolute;
            top: calc(#{$circle-width} + #{$gutter-width});
            left: 0;
            text-align: center;
          }
          &.figure-circle-label--left {
            position: absolute;
            right: calc(#{$circle-width} + #{$gutter-width});
            top: 0;
            display: flex;
            align-items: center;
            justify-content: flex-end;
            min-height: $circle-width;
            text-align: right;
          }
        }
      }
    }
  }
}
</style>

<style lang="scss">
/* 连线中的label 样式*/
.jtk-overlay {
  cursor: pointer;
  color: #4a4a4a;
  &.flowLabel:not(.aLabel) {
    padding: 1px 6px;
    background-color: #dcdfe6;
    color: #333 !important;
    border-radius: 5px;
    font-size: 12px;
    display: inline-block;
  }
}
.jtk-hover {
  cursor: pointer;
  &.flowLabel {
    //border-color: $--color-danger !important;
  }
}
</style>
